home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / oleo-1_4.lha / oleo-1.4 / basic.c < prev    next >
C/C++ Source or Header  |  1993-05-23  |  37KB  |  2,192 lines

  1. /*    Copyright (C) 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17.  
  18. #include <ctype.h>
  19. #include "sysdef.h"
  20. #include "global.h"
  21. #include "basic.h"
  22. #include "cmd.h"
  23. #include "regions.h"
  24. #include "window.h"
  25. #include "io-term.h"
  26. #include "io-generic.h"
  27. #include "io-abstract.h"
  28. #include "io-utils.h"
  29. #include "io-curses.h"
  30. #include "ref.h"
  31. #include "format.h"
  32. #include "lists.h"
  33. #include "io-edit.h"
  34. #include "eval.h"
  35. #include "byte-compile.h"
  36.  
  37.  
  38. /* Used by motion commands. */
  39. const int colmagic[] = {0, 0, 1, -1, 1, -1, 1, -1, 0};
  40. const int rowmagic[] = {-1, 1, 0, 0, -1, -1, 1, 1, 0};
  41.  
  42. char * motion_name[] =  
  43. {
  44.   "up",
  45.   "down",
  46.   "right",
  47.   "left",
  48.   "up right",
  49.   "up left",
  50.   "down right",
  51.   "down left",
  52.   "no motion"
  53. };
  54.  
  55.  
  56. /* This table ought to be a user parameter. */
  57. enum motion_magic complementary_motion[] = 
  58. {
  59.   magic_right,
  60.   magic_right,
  61.   magic_down,
  62.   magic_down,
  63.   magic_right,
  64.   magic_right,
  65.   magic_right,
  66.   magic_right,
  67.   magic_no_motion,
  68. };
  69.  
  70. enum motion_magic opposite_motion[] = 
  71. {
  72.   magic_down,
  73.   magic_up,
  74.   magic_left,
  75.   magic_right,
  76.   magic_down_left,
  77.   magic_down_right,
  78.   magic_up_left,
  79.   magic_up_right,
  80.   magic_no_motion,
  81. };
  82.  
  83.  
  84. /* Indexed by MAGIC + 1 */
  85. const int boundrymagic[3] = { MIN_ROW, NON_ROW, MAX_ROW };
  86.  
  87.  
  88.  
  89.  
  90. /* A very basic command. */
  91.  
  92. #ifdef __STDC__
  93. void
  94. noop (void)
  95. #else
  96. void
  97. noop ()
  98. #endif
  99. {}
  100.  
  101.  
  102.  
  103. /* Commands that inser/delete rows/columns. */
  104.  
  105. #ifdef __STDC__
  106. void
  107. insert_row (int repeat)
  108. #else
  109. void
  110. insert_row (repeat)
  111.      int repeat;
  112. #endif
  113. {
  114.   struct rng from;
  115.   struct rng to;
  116.   if ((repeat > (MAX_ROW - curow)) || (repeat < 0))
  117.     {
  118.       io_error_msg ("insert-row: prefix argument out of range.");
  119.       return;
  120.     }
  121.   from.lc = MIN_COL;
  122.   from.hc = MAX_COL;
  123.   from.lr = curow;
  124.   from.hr = MAX_ROW - repeat;
  125.   to.lc = MIN_COL;
  126.   to.hc = MIN_COL;
  127.   to.lr = curow + repeat;
  128.   to.hr = curow + repeat;
  129.   move_region (&from, &to);
  130. }
  131.  
  132. #ifdef __STDC__
  133. void
  134. insert_col (int repeat)
  135. #else
  136. void
  137. insert_col (repeat)
  138.      int repeat;
  139. #endif
  140. {
  141.   struct rng from;
  142.   struct rng to;
  143.   if ((repeat > (MAX_COL - cucol)) || (repeat < 0))
  144.     {
  145.       io_error_msg ("insert-col: prefix argument out of range.");
  146.       return;
  147.     }
  148.   from.lr = MIN_ROW;
  149.   from.hr = MAX_ROW;
  150.   from.lc = cucol;
  151.   from.hc = MAX_COL - repeat;
  152.   to.lr = MIN_ROW;
  153.   to.hr = MIN_ROW;
  154.   to.lc = cucol + repeat;
  155.   to.hc = cucol + repeat;
  156.   move_region (&from, &to);
  157. }
  158.  
  159. #ifdef __STDC__
  160. void
  161. delete_row (int repeat)
  162. #else
  163. void
  164. delete_row (repeat)
  165.      int repeat;
  166. #endif
  167. {
  168.   struct rng from;
  169.   struct rng to;
  170.   if ((repeat < 0) || (repeat > (MAX_ROW - curow + 1)))
  171.     {
  172.       io_error_msg ("delete-row: prefix argument out of range.");
  173.       return;
  174.     }
  175.   from.lc = MIN_COL;
  176.   from.hc = MAX_COL;
  177.   from.lr = curow + repeat;
  178.   from.hr = MAX_ROW;
  179.   to.lc = MIN_COL;
  180.   to.hc = MIN_COL;
  181.   to.lr = curow;
  182.   to.hr = curow;
  183.   move_region (&from, &to);
  184. }
  185.  
  186. #ifdef __STDC__
  187. void
  188. delete_col (int repeat)
  189. #else
  190. void
  191. delete_col (repeat)
  192.      int repeat;
  193. #endif
  194. {
  195.   struct rng from;
  196.   struct rng to;
  197.   if ((repeat < 0) || (repeat > (MAX_COL - cucol + 1)))
  198.     {
  199.       io_error_msg ("delete-col: prefix argument out of range.");
  200.       return;
  201.     }
  202.   from.lr = MIN_ROW;
  203.   from.hr = MAX_ROW;
  204.   from.lc = cucol + repeat;
  205.   from.hc = MAX_COL;
  206.   to.lr = MIN_ROW;
  207.   to.hr = MIN_ROW;
  208.   to.lc = cucol;
  209.   to.hc = cucol;
  210.   move_region (&from, &to);
  211. }
  212.  
  213.  
  214.  
  215. /* Front end to the window functions. */
  216.  
  217. #ifdef __STDC__
  218. void 
  219. open_window (char *text)
  220. #else
  221. void 
  222. open_window (text)
  223.      char *text;
  224. #endif
  225. {
  226.   int hv;
  227.   int where;
  228.  
  229.   while (*text == ' ')
  230.     text++;
  231.  
  232.   if (*text == 'h' || *text == 'H')
  233.     hv = 0;
  234.   else if (*text == 'v' || *text == 'V')
  235.     hv = 1;
  236.   else
  237.     {
  238.       io_error_msg ("Open 'h'orizontal or 'v'ertical window, not '%s'", text);
  239.       return;
  240.     }
  241.   where = atoi (text + 1);
  242.   while (isspace (*text))
  243.     ++text;
  244.   while (isalnum (*text))
  245.     ++text;
  246.   while (isspace (*text))
  247.     ++text;
  248.   if (*text == '%')
  249.     {
  250.       where *= (hv
  251.         ? (cwin->numr + (cwin->lh_wid ? label_rows : 0))
  252.         : (cwin->numc + cwin->lh_wid));
  253.       where /= 100;
  254.     }
  255.   io_win_open (hv, where);
  256. }
  257.  
  258. #ifdef __STDC__
  259. void
  260. hsplit_window (void)
  261. #else
  262. void
  263. hsplit_window ()
  264. #endif
  265. {
  266.   open_window ("h50%");
  267. }
  268.  
  269.  
  270. #ifdef __STDC__
  271. void
  272. vsplit_window (void)
  273. #else
  274. void
  275. vsplit_window ()
  276. #endif
  277. {
  278.   open_window ("v50%");
  279. }
  280.  
  281.  
  282. #ifdef __STDC__
  283. void 
  284. close_window (char *text)
  285. #else
  286. void 
  287. close_window (text)
  288.      char *text;
  289. #endif
  290. {
  291.   int num;
  292.  
  293.   num = atoi (text) - 1;
  294.  
  295.   if (num < 0 || num >= nwin)
  296.     {
  297.       io_error_msg ("Window %num?", text);
  298.       return;
  299.     }
  300.   if (nwin == 1)
  301.     {
  302.       io_error_msg ("You can't close the last window!");
  303.       return;
  304.     }
  305.   io_win_close (&wins[num]);
  306. }
  307.  
  308. #ifdef __STDC__
  309. void 
  310. delete_window (void)
  311. #else
  312. void 
  313. delete_window ()
  314. #endif
  315. {
  316.   io_win_close (cwin);
  317. }
  318.  
  319. #ifdef __STDC__
  320. void
  321. delete_other_windows (void)
  322. #else
  323. void
  324. delete_other_windows ()
  325. #endif
  326. {
  327.   if (nwin > 1)
  328.     {
  329.       CELLREF r = curow;
  330.       CELLREF c = cucol;
  331.       while (nwin > 1)
  332.     io_win_close (cwin);
  333.       io_move_cell_cursor (r, c);
  334.     }
  335. }
  336.  
  337. #ifdef __STDC__
  338. void 
  339. nicely_goto_window (int n)
  340. #else
  341. void 
  342. nicely_goto_window (n)
  343.      int n;
  344. #endif
  345. {
  346.   if (input_active)
  347.     {
  348.       io_cellize_cursor ();
  349.       window_after_input = n;
  350.       input_active = 0;
  351.       the_cmd_frame->top_keymap = map_id ("main");
  352.       return;
  353.     }
  354.   else
  355.     {
  356.       if ((window_after_input >= 0)
  357.       && ((window_after_input % nwin) == n))
  358.     {
  359.       io_inputize_cursor ();
  360.       window_after_input = -1;
  361.       input_active = 1;
  362.       the_cmd_frame->top_keymap =
  363.         map_id (the_cmd_frame->cmd
  364.             ? the_cmd_arg.style->keymap
  365.             : "main");
  366.     }
  367.       else
  368.     io_set_cwin (&wins[n]);
  369.     }
  370. }
  371.  
  372. #ifdef __STDC__
  373. void
  374. goto_minibuffer (void)
  375. #else
  376. void
  377. goto_minibuffer ()
  378. #endif
  379. {
  380.   if (window_after_input < 0)
  381.     {
  382.       if (!input_active)
  383.     io_error_msg ("Minibuffer not active.");
  384.     }
  385.   else
  386.     nicely_goto_window ((window_after_input % nwin));
  387. }
  388.  
  389.  
  390. #ifdef __STDC__
  391. void
  392. goto_window (char *text)
  393. #else
  394. void
  395. goto_window (text)
  396.      char *text;
  397. #endif
  398. {
  399.   int n;
  400.   n = atoi (text) - 1;
  401.   if (n < 0 || n > nwin)
  402.     {
  403.       io_error_msg ("Window %s doesn't exist.", text);
  404.       return;
  405.     }
  406.   else
  407.     nicely_goto_window (n);
  408. }
  409.  
  410.  
  411. #ifdef __STDC__
  412. void 
  413. other_window (void)
  414. #else
  415. void 
  416. other_window ()
  417. #endif
  418. {
  419.   int n = cwin - wins;
  420.   if (!input_active)
  421.     n = (n + 1) % nwin;
  422.   nicely_goto_window (n);
  423. }
  424.  
  425. #ifdef __STDC__
  426. int
  427. set_window_option (int set_opt, char *text)
  428. #else
  429. int
  430. set_window_option (set_opt, text)
  431.      int set_opt;
  432.      char *text;
  433. #endif
  434. {
  435.   int n;
  436.   int stat;
  437.   static struct opt
  438.     {
  439.       char *text;
  440.       int bits;
  441.     }
  442.   opts[] =
  443.   {
  444.     {
  445.       "reverse", WIN_EDGE_REV
  446.     }
  447.     ,
  448.     {
  449.       "standout", WIN_EDGE_REV
  450.     }
  451.     ,
  452.     {
  453.       "page", WIN_PAG_HZ | WIN_PAG_VT
  454.     }
  455.     ,
  456.     {
  457.       "pageh", WIN_PAG_HZ
  458.     }
  459.     ,
  460.     {
  461.       "pagev", WIN_PAG_VT
  462.     }
  463.     ,
  464.     {
  465.       "lockh", WIN_LCK_HZ
  466.     }
  467.     ,
  468.     {
  469.       "lockv", WIN_LCK_VT
  470.     }
  471.     ,
  472.     {
  473.       "edges", WIN_EDGES
  474.     }
  475.   };
  476.   if ((stat = (!strincmp (text, "status", 6) && isspace (text[6])))
  477.       || (!strincmp (text, "input", 5) && isspace (text[5])))
  478.     {
  479.       int n = set_opt ? atoi (text + 6 + stat) : 0;    /* A little pun. */
  480.       int new_inp = stat ? user_input : n;
  481.       int new_stat = stat ? n : user_status;
  482.       io_set_input_status (new_inp, new_stat, 1);
  483.     }
  484.   else if (!strincmp (text, "link", 4))
  485.     {
  486.       if (set_opt)
  487.     {
  488.       n = atoi (text + 4) - 1;
  489.       if (n < 0 || n > nwin)
  490.         io_error_msg ("Can't '%s': window # out of range", text);
  491.       else
  492.         cwin->link = n;
  493.     }
  494.       else
  495.     cwin->link = -1;
  496.     }
  497.   else if (set_opt && !stricmp (text, "unlink"))
  498.     cwin->link = -1;
  499.   else if (set_opt && !strincmp (text, "row ", 4))
  500.     {
  501.       text += 4;
  502.       curow = astol (&text);
  503.     }
  504.   else if (set_opt && !strincmp (text, "col ", 4))
  505.     {
  506.       text += 4;
  507.       cucol = astol (&text);
  508.     }
  509.   else
  510.     {
  511.       for (n = 0; n < sizeof (opts) / sizeof (struct opt); n++)
  512.     if (!stricmp (text, opts[n].text))
  513.       {
  514.         if (set_opt)
  515.           cwin->flags |= opts[n].bits;
  516.         else
  517.           cwin->flags &= ~opts[n].bits;
  518.         break;
  519.       }
  520.  
  521.       if (n == sizeof (opts) / sizeof (struct opt))
  522.       return 0;
  523.     }
  524.   return 1;
  525. }
  526.  
  527. #ifdef __STDC__
  528. void
  529. show_window_options (void)
  530. #else
  531. void
  532. show_window_options ()
  533. #endif
  534. {
  535.   int n;
  536.  
  537.   cwin->win_curow = curow;
  538.   cwin->win_cucol = cucol;
  539.   if (user_status)
  540.     io_text_line ("Status line at %d", user_status);
  541.   else
  542.     io_text_line ("Status line disabled.");
  543.   io_text_line ("");
  544.   for (n = 0; n < nwin; n++)
  545.     {
  546.       int flags = wins[n].flags;
  547.       io_text_line ("Window #%d showing %s, with cursor at %s",
  548.             n + 1,
  549.             range_name (&wins[n].screen),
  550.             cell_name (wins[n].win_curow, wins[n].win_cucol));
  551.       io_text_line ("   Options:  %sedges (%sreverse)%s%s%s%s",
  552.             flags & WIN_EDGES ? "" : "no",
  553.             flags & WIN_EDGE_REV ? "" : "no",
  554.             flags & WIN_PAG_HZ ? ", pageh" : "",
  555.             flags & WIN_PAG_VT ? ", pagev" : "",
  556.             flags & WIN_LCK_HZ ? ", lockh" : "",
  557.             flags & WIN_LCK_VT ? ", lockv" : "");
  558.       if (wins[n].link != -1)
  559.     io_text_line ("Linked to window %d", wins[n].link + 1);
  560.     }
  561. }
  562.  
  563. #ifdef __STDC__
  564. void
  565. recenter_window (void)
  566. #else
  567. void
  568. recenter_window ()
  569. #endif
  570. {
  571.   io_recenter_cur_win ();
  572. }
  573.  
  574.  
  575.  
  576. /* Trivial front-end commands. */
  577.  
  578.  
  579. #ifdef __STDC__
  580. void
  581. suspend_oleo (void)
  582. #else
  583. void
  584. suspend_oleo ()
  585. #endif
  586. {
  587.   if (using_curses)
  588.     {
  589.       stop_curses ();
  590. #ifdef SIGTSTP
  591.       kill (getpid (), SIGTSTP);
  592. #else
  593.        kill (getpid (), SIGSTOP);
  594. #endif
  595.       cont_curses ();
  596.       kill (getpid (), SIGSTOP);
  597.     }
  598. }
  599.  
  600. #ifdef __STDC__
  601. void
  602. recalculate (int all)
  603. #else
  604. void
  605. recalculate (all)
  606.      int all;
  607. #endif
  608. {
  609.   current_cycle++;
  610.   if (all)
  611.     {
  612.       CELLREF row;
  613.       CELLREF col;
  614.       struct rng all;
  615.       all.lr = MIN_ROW;
  616.       all.hr = MAX_ROW;
  617.       all.lc = MIN_COL;
  618.       all.hc = MAX_COL;
  619.       find_cells_in_range (&all);
  620.       while (next_row_col_in_range (&row, &col))
  621.     push_cell (row, col);
  622.     }
  623.   while (eval_next_cell ())
  624.     ;
  625. }
  626.  
  627.  
  628. #ifdef __STDC__
  629. void
  630. kill_oleo (void)
  631. #else
  632. void
  633. kill_oleo ()
  634. #endif
  635. {
  636.   io_close_display ();
  637.   exit (0);
  638. }
  639.  
  640.  
  641. #ifdef __STDC__
  642. void
  643. kill_all_cmd (void)
  644. #else
  645. void
  646. kill_all_cmd ()
  647. #endif
  648. {
  649.   clear_spreadsheet ();
  650.   io_repaint ();
  651. }
  652.  
  653. #ifdef __STDC__
  654. void
  655. redraw_screen (void)
  656. #else
  657. void
  658. redraw_screen ()
  659. #endif
  660. {
  661.   io_repaint ();
  662. }
  663.  
  664.  
  665.  
  666. /* Motion commands. */
  667.  
  668. #ifdef __STDC__
  669. void
  670. shift_cell_cursor (int dir, int repeat)
  671. #else
  672. void
  673. shift_cell_cursor (dir, repeat)
  674.      int dir;
  675.      int repeat;
  676. #endif
  677. {
  678.   io_shift_cell_cursor (dir, repeat);
  679. }
  680.  
  681.  
  682. #ifdef __STDC__
  683. void
  684. scroll_cell_cursor (int dir, int repeat)
  685. #else
  686. void
  687. scroll_cell_cursor (dir, repeat)
  688.      int dir;
  689.      int repeat;
  690. #endif
  691. {
  692.   io_scroll_cell_cursor (dir, repeat);
  693. }
  694.  
  695.  
  696.  
  697. #ifdef __STDC__
  698. void
  699. goto_region (struct rng *r)
  700. #else
  701. void
  702. goto_region (r)
  703.      struct rng *r;
  704. #endif
  705. {
  706.   (void) io_move_cell_cursor (r->lr, r->lc);
  707.  
  708.   if (r->hr != r->lr || r->hc != r->lc)
  709.     {
  710.       mkrow = r->hr;
  711.       mkcol = r->hc;
  712.     }
  713.   else if (mkrow != NON_ROW)
  714.     mkrow = NON_ROW;
  715.   io_update_status ();
  716. }
  717.  
  718. #ifdef __STDC__
  719. void
  720. goto_cell (struct rng * rng)
  721. #else
  722. void
  723. goto_cell (rng)
  724.      struct rng * rng;
  725. #endif
  726. {
  727.   rng->hr = mkrow;
  728.   rng->hc = mkcol;
  729.   goto_region (rng);
  730. }
  731.  
  732. #ifdef __STDC__
  733. void
  734. exchange_point_and_mark (int clrmk)
  735. #else
  736. void
  737. exchange_point_and_mark (clrmk)
  738.      int clrmk;
  739. #endif
  740. {
  741.   struct rng rng;
  742.   if (clrmk)
  743.     {
  744.       rng.lr = curow;
  745.       rng.lc = cucol;
  746.       rng.hr = NON_ROW;
  747.       rng.hc = NON_COL;
  748.       goto_region (&rng);
  749.     }
  750.   else if (mkrow != NON_ROW)
  751.     {
  752.       rng.lr = mkrow;
  753.       rng.lc = mkcol;
  754.       rng.hr = curow;
  755.       rng.hc = cucol;
  756.       goto_region (&rng);
  757.     }
  758. }
  759.  
  760. #ifdef __STDC__
  761. static CELLREF
  762. first_filled_col (CELLREF row)
  763. #else
  764. static CELLREF
  765. first_filled_col (row)
  766.      CELLREF row;
  767. #endif
  768. {
  769.   struct rng rng;
  770.   CELLREF r;
  771.   CELLREF c;
  772.   rng.lr = row;
  773.   rng.hr = row;
  774.   rng.lc = MIN_COL;
  775.   rng.hc = MAX_COL;
  776.   find_cells_in_range (&rng);
  777.   while (1)
  778.     {
  779.       CELL * cp;
  780.       cp = next_row_col_in_range (&r, &c);
  781.       if (!cp)
  782.     break;
  783.       if (GET_TYP(cp))
  784.     {
  785.       no_more_cells ();
  786.       return c;
  787.     }
  788.     }
  789.   return NON_COL;
  790. }
  791.  
  792. #ifdef __STDC__
  793. static CELLREF
  794. last_filled_col (CELLREF row)
  795. #else
  796. static CELLREF
  797. last_filled_col (row)
  798.      CELLREF row;
  799. #endif
  800. {
  801.   struct rng rng;
  802.   CELLREF r;
  803.   CELLREF c;
  804.   CELLREF bestc = MIN_COL;
  805.   rng.lr = row;
  806.   rng.hr = row;
  807.   rng.lc = MIN_COL;
  808.   rng.hc = MAX_COL;
  809.   find_cells_in_range (&rng);
  810.   while (1)
  811.     {
  812.       CELL * cp;
  813.       cp = next_row_col_in_range (&r, &c);
  814.       if (!cp)
  815.     break;
  816.       if (GET_TYP(cp))
  817.     bestc = c;
  818.     }
  819.   return bestc;
  820. }
  821.  
  822. #ifdef __STDC__
  823. static CELLREF
  824. first_filled_row (CELLREF col)
  825. #else
  826. static CELLREF
  827. first_filled_row (col)
  828.      CELLREF col;
  829. #endif
  830. {
  831.   struct rng rng;
  832.   CELLREF r;
  833.   CELLREF c;
  834.   CELL * cp;
  835.   rng.lr = MIN_ROW;
  836.   rng.hr = MAX_ROW;
  837.   rng.lc = col;
  838.   rng.hc = col;
  839.   find_cells_in_range (&rng);
  840.   while (1)
  841.     {
  842.       cp = next_row_col_in_range (&r, &c);
  843.       if (!cp)
  844.     break;
  845.       if (GET_TYP(cp))
  846.     {
  847.       no_more_cells ();
  848.       return r;
  849.     }
  850.     }
  851.   return NON_ROW;
  852. }
  853.  
  854. #ifdef __STDC__
  855. static CELLREF
  856. last_filled_row (CELLREF col)
  857. #else
  858. static CELLREF
  859. last_filled_row (col)
  860.      CELLREF col;
  861. #endif
  862. {
  863.   struct rng rng;
  864.   CELLREF r;
  865.   CELLREF c;
  866.   CELLREF bestr = MIN_ROW;
  867.   CELL * cp;
  868.   rng.lr = MIN_ROW;
  869.   rng.hr = MAX_ROW;
  870.   rng.lc = col;
  871.   rng.hc = col;
  872.   find_cells_in_range (&rng);
  873.   while (1)
  874.     {
  875.       cp = next_row_col_in_range (&r, &c);
  876.       if (!cp)
  877.     break;
  878.       if (GET_TYP(cp))
  879.     bestr = r;
  880.     }
  881.   return bestr;
  882. }
  883.  
  884. #ifdef __STDC__
  885. static CELLREF
  886. max_filled_row (void)
  887. #else
  888. static CELLREF
  889. max_filled_row ()
  890. #endif
  891. {
  892.   CELLREF max_r = highest_row ();
  893.   while (max_r != MIN_ROW)
  894.     {
  895.       CELLREF c = first_filled_col (max_r);
  896.       if (c != NON_COL)
  897.     break;
  898.       --max_r;
  899.     }
  900.   return max_r;
  901. }
  902.  
  903.  
  904. #ifdef __STDC__
  905. static CELLREF
  906. max_filled_col (void)
  907. #else
  908. static CELLREF
  909. max_filled_col ()
  910. #endif
  911. {
  912.   CELLREF max_c = highest_col ();
  913.   while (max_c != MIN_COL)
  914.     {
  915.       CELLREF r = first_filled_row (max_c);
  916.       if (r != NON_COL)
  917.     break;
  918.       --max_c;
  919.     }
  920.   return max_c;
  921. }
  922.  
  923. #ifdef __STDC__
  924. static void 
  925. mk_for_extreme (struct rng * rng)
  926. #else
  927. static void 
  928. mk_for_extreme (rng)
  929.      struct rng * rng;
  930. #endif
  931. {
  932.   if (mkrow != NON_ROW)
  933.     {
  934.       rng->hr = mkrow;
  935.       rng->hc = mkcol;
  936.     }
  937.   else
  938.     {
  939.       rng->hc = cucol;
  940.       rng->hr = curow;
  941.     }
  942. }
  943.  
  944. #ifdef __STDC__
  945. void
  946. upper_left (void)
  947. #else
  948. void
  949. upper_left ()
  950. #endif
  951. {
  952.   struct rng rng;
  953.   rng.lr = MIN_ROW;
  954.   rng.lc = MIN_COL;
  955.   mk_for_extreme (&rng);
  956.   goto_region (&rng);
  957. }
  958.  
  959. #ifdef __STDC__
  960. void
  961. lower_left (void)
  962. #else
  963. void
  964. lower_left ()
  965. #endif
  966. {
  967.   struct rng rng;
  968.   rng.lr = max_filled_row ();
  969.   rng.lc = MIN_COL;
  970.   mk_for_extreme (&rng);
  971.   goto_region (&rng);
  972. }
  973.  
  974. #ifdef __STDC__
  975. void
  976. upper_right (void)
  977. #else
  978. void
  979. upper_right ()
  980. #endif
  981. {
  982.   struct rng rng;
  983.   rng.lr = MIN_ROW;
  984.   rng.lc = max_filled_col ();
  985.   mk_for_extreme (&rng);
  986.   goto_region (&rng);
  987. }
  988.  
  989. #ifdef __STDC__
  990. void
  991. lower_right (void)
  992. #else
  993. void
  994. lower_right ()
  995. #endif
  996. {
  997.   struct rng rng;
  998.   rng.lr = max_filled_row ();
  999.   rng.lc = max_filled_col ();
  1000.   mk_for_extreme (&rng);
  1001.   goto_region (&rng);
  1002. }
  1003.  
  1004. #ifdef __STDC__
  1005. void
  1006. mark_cell_cmd (int popmk)
  1007. #else
  1008. void
  1009. mark_cell_cmd (popmk)
  1010.      int popmk;
  1011. #endif
  1012. {
  1013.   if (popmk)
  1014.     {
  1015.       if (mkrow != NON_ROW)
  1016.     {
  1017.       struct rng rng;
  1018.       rng.lr = mkrow;
  1019.       rng.lc = mkcol;
  1020.       rng.hr = NON_ROW;
  1021.       rng.hc = NON_COL;
  1022.       goto_region (&rng);
  1023.     }
  1024.     }
  1025.   else
  1026.     {
  1027.       mkrow = curow;
  1028.       mkcol = cucol;
  1029.       io_update_status ();
  1030.     }
  1031. }
  1032.  
  1033. #ifdef __STDC__
  1034. void
  1035. unmark_cmd (void)
  1036. #else
  1037. void
  1038. unmark_cmd ()
  1039. #endif
  1040. {
  1041.   mkrow = NON_ROW;
  1042.   mkcol = NON_COL;
  1043.   io_update_status ();
  1044. }
  1045.  
  1046.  
  1047. /* This is a bit kludgey. Input line editting has its own event loop (grr!),
  1048.  * and all of its state is private.  These mouse commands can't entirely
  1049.  * handle it when the target is in the input line.  In that case, they
  1050.  * save the decoded mouse event where io_get_line can pick it up:
  1051.  */
  1052. struct mouse_event last_mouse_event;
  1053.  
  1054. #ifdef __STDC__
  1055. void
  1056. do_mouse_goto (void)
  1057. #else
  1058. void
  1059. do_mouse_goto ()
  1060. #endif
  1061. {
  1062.   if (!last_mouse_event.downp)
  1063.     return;
  1064.   if (last_mouse_event.location >= 0 && last_mouse_event.downp)
  1065.     {
  1066.       if (input_active)
  1067.     {
  1068.       io_cellize_cursor ();
  1069.       window_after_input = last_mouse_event.location;
  1070.       input_active = 0;
  1071.       the_cmd_frame->top_keymap = map_id ("main");
  1072.     }
  1073.       io_set_cwin (&wins[last_mouse_event.location]);
  1074.       io_move_cell_cursor (last_mouse_event.r, last_mouse_event.c);
  1075.     }
  1076.   else if (last_mouse_event.location == MOUSE_ON_INPUT)
  1077.     {
  1078.       goto_minibuffer ();
  1079. #ifdef HAVE_X11_X_H
  1080.       if (using_x)
  1081.     goto_char (io_col_to_input_pos (last_mouse_event.col));
  1082. #endif
  1083.     }
  1084.   else
  1085.     io_bell ();
  1086. }
  1087.  
  1088. #ifdef __STDC__
  1089. void
  1090. do_mouse_mark (void)
  1091. #else
  1092. void
  1093. do_mouse_mark ()
  1094. #endif
  1095. {
  1096.   if (last_mouse_event.location >= 0 && last_mouse_event.downp)
  1097.     {
  1098.       mkrow = last_mouse_event.r;
  1099.       mkcol = last_mouse_event.c;
  1100.     }
  1101. }
  1102.  
  1103.  
  1104. #ifdef __STDC__
  1105. void
  1106. do_mouse_mark_and_goto (void)
  1107. #else
  1108. void
  1109. do_mouse_mark_and_goto ()
  1110. #endif
  1111. {
  1112.   if (last_mouse_event.location >= 0 && last_mouse_event.downp)
  1113.     {
  1114.       mkrow = curow;
  1115.       mkcol = cucol;
  1116.     }
  1117.   do_mouse_goto ();
  1118. }
  1119.  
  1120. #ifdef __STDC__
  1121. void
  1122. do_mouse_cmd (void (*fn) ())
  1123. #else
  1124. void
  1125. do_mouse_cmd (fn)
  1126.      void (*fn) ();
  1127. #endif
  1128. {
  1129.   int seq = real_get_chr ();
  1130.   dequeue_mouse_event (&last_mouse_event, seq);
  1131.   fn ();
  1132. }
  1133.  
  1134. #ifdef __STDC__
  1135. void
  1136. mouse_mark_cmd (void)
  1137. #else
  1138. void
  1139. mouse_mark_cmd ()
  1140. #endif
  1141. {
  1142.   do_mouse_cmd (do_mouse_mark);
  1143. }
  1144.  
  1145.  
  1146. #ifdef __STDC__
  1147. void
  1148. mouse_goto_cmd (void)
  1149. #else
  1150. void
  1151. mouse_goto_cmd ()
  1152. #endif
  1153. {
  1154.   do_mouse_cmd (do_mouse_goto);
  1155. }
  1156.  
  1157. #ifdef __STDC__
  1158. void
  1159. mouse_mark_and_goto_cmd (void)
  1160. #else
  1161. void
  1162. mouse_mark_and_goto_cmd ()
  1163. #endif
  1164. {
  1165.   do_mouse_cmd (do_mouse_mark_and_goto);
  1166. }
  1167.  
  1168.  
  1169.  
  1170. /* Commands used to modify cell formulas. */
  1171.  
  1172. #ifdef __STDC__
  1173. void 
  1174. kill_cell_cmd (void)
  1175. #else
  1176. void 
  1177. kill_cell_cmd ()
  1178. #endif
  1179. {
  1180.   CELL *cp;
  1181.  
  1182.   cp = find_cell (curow, cucol);
  1183.   if (!cp)
  1184.     return;
  1185.   if ((GET_LCK (cp) == LCK_DEF && default_lock == LCK_LCK) || GET_LCK (cp) == LCK_LCK)
  1186.     {
  1187.       io_error_msg ("Cell %s is locked", cell_name (curow, cucol));
  1188.       return;
  1189.     }
  1190.   new_value (curow, cucol, "");
  1191.   cp->cell_flags = 0;
  1192.   cp->cell_font = 0;
  1193.   modified = 1;
  1194. }
  1195.  
  1196.  
  1197.  
  1198.  
  1199. /* A front end to sorting. */
  1200.  
  1201. #ifdef __STDC__
  1202. void
  1203. sort_region_cmd (char *ptr)
  1204. #else
  1205. void
  1206. sort_region_cmd (ptr)
  1207.      char *ptr;
  1208. #endif
  1209. {
  1210.   struct rng tmp_rng;
  1211.  
  1212.   if (get_abs_rng (&ptr, &sort_rng))
  1213.     {
  1214.       io_error_msg ("Can't find a range to sort in %s", ptr);
  1215.       return;
  1216.     }
  1217.  
  1218.   cur_row = sort_rng.lr;
  1219.   cur_col = sort_rng.lc;
  1220.  
  1221.   while (*ptr == ' ')
  1222.     ptr++;
  1223.   if (!*ptr)
  1224.     {
  1225.       sort_ele.lr = 0;
  1226.       sort_ele.lc = 0;
  1227.       sort_ele.hr = 0;
  1228.       sort_ele.hc = 0;
  1229.     }
  1230.   else if (!parse_cell_or_range (&ptr, &sort_ele))
  1231.     {
  1232.       io_error_msg ("Can't parse elements in %s", ptr);
  1233.       return;
  1234.     }
  1235.   else
  1236.     {
  1237.       sort_ele.lr -= sort_rng.lr;
  1238.       sort_ele.lc -= sort_rng.lc;
  1239.       sort_ele.hr -= sort_rng.lr;
  1240.       sort_ele.hc -= sort_rng.lc;
  1241.     }
  1242.  
  1243.   sort_keys_num = 0;
  1244.   while (*ptr == ' ')
  1245.     ptr++;
  1246.   for (; *ptr;)
  1247.     {
  1248.       if (sort_keys_num == sort_keys_alloc)
  1249.     {
  1250.       sort_keys_alloc++;
  1251.       if (sort_keys_alloc > 1)
  1252.         sort_keys = ck_realloc (sort_keys, sort_keys_alloc * sizeof (struct cmp));
  1253.       else
  1254.         sort_keys = ck_malloc (sizeof (struct cmp));
  1255.     }
  1256.       sort_keys[sort_keys_num].mult = 1;
  1257.       if (*ptr == '+')
  1258.     ptr++;
  1259.       else if (*ptr == '-')
  1260.     {
  1261.       sort_keys[sort_keys_num].mult = -1;
  1262.       ptr++;
  1263.     }
  1264.       if (!*ptr)
  1265.     {
  1266.       sort_keys[sort_keys_num].row = 0;
  1267.       sort_keys[sort_keys_num].col = 0;
  1268.       sort_keys_num++;
  1269.       break;
  1270.     }
  1271.       if (!parse_cell_or_range (&ptr, &tmp_rng) || tmp_rng.lr != tmp_rng.hr || tmp_rng.lc != tmp_rng.hc)
  1272.     {
  1273.       io_error_msg ("Can't parse key #%d in %s", sort_keys_num + 1, ptr);
  1274.       sort_keys_num = -1;
  1275.       return;
  1276.     }
  1277.       sort_keys[sort_keys_num].row = tmp_rng.lr - sort_rng.lr;
  1278.       sort_keys[sort_keys_num].col = tmp_rng.lc - sort_rng.lc;
  1279.       sort_keys_num++;
  1280.  
  1281.       while (*ptr == ' ')
  1282.     ptr++;
  1283.     }
  1284.   if (sort_keys_num == 0)
  1285.     {
  1286.       if (sort_keys_alloc == 0)
  1287.     {
  1288.       sort_keys_alloc++;
  1289.       sort_keys = ck_malloc (sizeof (struct cmp));
  1290.     }
  1291.       sort_keys[0].mult = 1;
  1292.       sort_keys[0].row = 0;
  1293.       sort_keys[0].col = 0;
  1294.       sort_keys_num++;
  1295.     }
  1296.   sort_region ();
  1297.   io_repaint ();
  1298. }
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304. #ifdef __STDC__
  1305. void
  1306. imove (struct rng * rng, int ch)
  1307. #else
  1308. void
  1309. imove (rng, ch)
  1310.      struct rng * rng;
  1311.      int ch;
  1312. #endif
  1313. {
  1314.   if ((ch > 0) && (ch != 27))
  1315.     pushed_back_char = ch;
  1316.  
  1317.   goto_region (rng);
  1318. }
  1319.  
  1320.  
  1321.  
  1322.  
  1323. /* Incremental navigation
  1324.  *
  1325.  * This should be called in edit mode while gathering arguments 
  1326.  * for a complex command.  The expected the_cmd_arg.
  1327.  */
  1328.  
  1329. #define MIN(A,B)    ((A) < (B) ? (A) : (B))
  1330.  
  1331. /* PAGE_RULE can be 0: page by  rows, 1: cols, 2 shorter of rows/cols,
  1332.  *               -1: don't page at all.
  1333.  */
  1334.  
  1335. #ifdef __STDC__
  1336. void
  1337. inc_direction (int count, int page_rule, int hack_magic)
  1338. #else
  1339. void
  1340. inc_direction (count, page_rule, hack_magic)
  1341.      int count;
  1342.      int page_rule;
  1343.      int hack_magic;
  1344. #endif
  1345. {
  1346.   if (check_editting_mode ())
  1347.     return;
  1348.  
  1349.   if (page_rule >= 0)
  1350.     {
  1351.       int page_size;
  1352.  
  1353.       switch (page_rule)
  1354.     {
  1355.     default:
  1356.     case 0:
  1357.       page_size = (cwin->screen.hr - cwin->screen.lr);
  1358.       break;
  1359.     case 1:
  1360.       page_size = (cwin->screen.hc - cwin->screen.lc);
  1361.       break;
  1362.     case 2:
  1363.       page_size = MIN ((cwin->screen.hr - cwin->screen.lr),
  1364.                (cwin->screen.hc - cwin->screen.lc));
  1365.       break;
  1366.     }
  1367.       count *= page_size;
  1368.     }
  1369.  
  1370.   if (the_cmd_frame->cmd && the_cmd_arg.inc_cmd)
  1371.     the_cmd_arg.inc_cmd (hack_magic, count);
  1372. }
  1373.  
  1374.  
  1375.  
  1376.  
  1377. /* The commands that move to the extreme of a row[col] may also move
  1378.  * forward or backward some number of col[row], according to the prefix
  1379.  * arg.  This is the logic of that.  This function returns the new col[row]
  1380.  * and operates on the presumption that MIN_ROW == MIN_COL and
  1381.  * MAX_ROW == MAX_COL.
  1382.  */
  1383.  
  1384. #ifdef __STDC__
  1385. static CELLREF
  1386. extreme_cmd_orth_motion (int count, CELLREF current)
  1387. #else
  1388. static CELLREF
  1389. extreme_cmd_orth_motion (count, current)
  1390.      int count;
  1391.      CELLREF current;
  1392. #endif
  1393. {
  1394.   --count;
  1395.   if (count > (MAX_ROW - current))
  1396.     count =  (MAX_ROW - current);
  1397.   else if (-count > (current - MIN_ROW))
  1398.     count = (MIN_ROW - current);
  1399.   return current + count;
  1400. }
  1401.  
  1402.  
  1403. #ifdef __STDC__
  1404. void
  1405. beginning_of_row (int count)
  1406. #else
  1407. void
  1408. beginning_of_row (count)
  1409.      int count;
  1410. #endif
  1411. {
  1412.   struct rng rng;
  1413.   rng.lr = extreme_cmd_orth_motion (count, curow);
  1414.   rng.lc = MIN_COL;
  1415.   rng.hr = mkrow;
  1416.   rng.hc = mkcol;
  1417.   goto_region (&rng);
  1418. }
  1419.  
  1420. #ifdef __STDC__
  1421. void
  1422. end_of_row (int count)
  1423. #else
  1424. void
  1425. end_of_row (count)
  1426.      int count;
  1427. #endif
  1428. {
  1429.   struct rng rng;
  1430.   rng.lr = extreme_cmd_orth_motion (count, curow);
  1431.   rng.lc = last_filled_col (rng.lr);
  1432.   rng.hr = mkrow;
  1433.   rng.hc = mkcol;
  1434.   goto_region (&rng);
  1435. }
  1436.  
  1437. #ifdef __STDC__
  1438. void
  1439. beginning_of_col (int count)
  1440. #else
  1441. void
  1442. beginning_of_col (count)
  1443.      int count;
  1444. #endif
  1445. {
  1446.   struct rng rng;
  1447.   rng.lr = MIN_ROW;
  1448.   rng.lc = extreme_cmd_orth_motion (count, cucol);
  1449.   rng.hr = mkrow;
  1450.   rng.hc = mkcol;
  1451.   goto_region (&rng);
  1452. }
  1453.  
  1454. #ifdef __STDC__
  1455. void
  1456. end_of_col (int count)
  1457. #else
  1458. void
  1459. end_of_col (count)
  1460.      int count;
  1461. #endif
  1462. {
  1463.   struct rng rng;
  1464.   rng.lc = extreme_cmd_orth_motion (count, cucol);
  1465.   rng.lr = last_filled_row (rng.lc);
  1466.   rng.hr = mkrow;
  1467.   rng.hc = mkcol;
  1468.   goto_region (&rng);
  1469. }
  1470.  
  1471.  
  1472. #ifdef __STDC__
  1473. static void
  1474. skip_empties (CELLREF * rout, CELLREF * cout, int magic)
  1475. #else
  1476. static void
  1477. skip_empties (rout, cout, magic)
  1478.      CELLREF * rout;
  1479.      CELLREF * cout;
  1480.      int magic;
  1481. #endif
  1482. {
  1483.   CELLREF r = *rout;
  1484.   CELLREF c = *cout;
  1485.   CELL * cp = find_cell (r, c);
  1486.  
  1487.   while (!cp || !GET_TYP (cp))
  1488.     {
  1489.       if (r != boundrymagic [rowmagic [magic] + 1])
  1490.     r += rowmagic [magic];
  1491.       else if (rowmagic [magic])
  1492.     break;
  1493.       if (c != boundrymagic [colmagic [magic] + 1])
  1494.     c += colmagic [magic];
  1495.       else if (colmagic[magic])
  1496.     break;
  1497.       cp = find_cell (r, c);
  1498.     }
  1499.  
  1500.   *rout = r;
  1501.   *cout = c;
  1502. }
  1503.  
  1504. #ifdef __STDC__
  1505. void
  1506. scan_cell_cursor (int magic, int count)
  1507. #else
  1508. void
  1509. scan_cell_cursor (magic, count)
  1510.      int magic;
  1511.      int count;
  1512. #endif
  1513. {
  1514.   CELLREF r = curow;
  1515.   CELLREF c = cucol;
  1516.   CELLREF last_r = r;
  1517.   CELLREF last_c = c;
  1518.  
  1519.   skip_empties (&r, &c, magic);
  1520.   {
  1521.     CELL * cp = find_cell (r, c);
  1522.     if (!(cp && GET_TYP (cp)))
  1523.       return;
  1524.   }
  1525.   while (count)
  1526.     {
  1527.       CELL * cp = find_cell (r, c);
  1528.       while (!cp || !GET_TYP (cp))
  1529.     {
  1530.       if (r != boundrymagic [rowmagic [magic] + 1])
  1531.         r += rowmagic [magic];
  1532.       else if (rowmagic [magic])
  1533.         break;
  1534.       if (c != boundrymagic [colmagic [magic] + 1])
  1535.         c += colmagic [magic];
  1536.       else if (colmagic[magic])
  1537.         break;
  1538.       cp = find_cell (r, c);
  1539.     }
  1540.       while (cp && GET_TYP (cp))
  1541.     {
  1542.       if (r != boundrymagic [rowmagic [magic] + 1])
  1543.         r += rowmagic [magic];
  1544.       else if (rowmagic[magic])
  1545.         break;
  1546.       if (c != boundrymagic [colmagic [magic] + 1])
  1547.         c += colmagic [magic];
  1548.       else if (colmagic [magic])
  1549.         break;
  1550.       last_r = r;
  1551.       last_c = c;
  1552.       cp = find_cell (r, c);
  1553.     }
  1554.       --count;
  1555.     }
  1556.   {
  1557.     struct rng rng;
  1558.     rng.lr = last_r;
  1559.     rng.lc = last_c;
  1560.     rng.hr = mkrow;
  1561.     rng.hc = mkcol;
  1562.     goto_region (&rng);
  1563.   }
  1564. }
  1565.  
  1566.  
  1567. #ifdef __STDC__
  1568. void
  1569. edit_cell (char * new_formula)
  1570. #else
  1571. void
  1572. edit_cell (new_formula)
  1573.      char * new_formula;
  1574. #endif
  1575. {
  1576.   char * fail;
  1577.   fail = new_value (setrow, setcol, new_formula);
  1578.   if (fail)
  1579.     io_error_msg (fail);
  1580.   else
  1581.     modified = 1;
  1582. }
  1583.  
  1584.  
  1585. #ifdef __STDC__
  1586. void
  1587. set_region_formula (struct rng * rng, char * str)
  1588. #else
  1589. void
  1590. set_region_formula (rng, str)
  1591.      struct rng * rng;
  1592.      char * str;
  1593. #endif
  1594. {
  1595.   CELLREF row, col;
  1596.  
  1597.   for (row = rng->lr; row <= rng->hr; ++row)
  1598.     for (col = rng->lc; col <= rng->hc; ++col)
  1599.       {
  1600.     char * error = new_value (row, col, str);
  1601.     if (!error)
  1602.       modified = 1;
  1603.     if (error)
  1604.       {
  1605.         io_error_msg (error);
  1606.         return;
  1607.       }
  1608.       }
  1609. }
  1610.  
  1611. #ifdef __STDC__
  1612. void
  1613. goto_edit_cell (int c)
  1614. #else
  1615. void
  1616. goto_edit_cell (c)
  1617.      int c;
  1618. #endif
  1619. {
  1620.   pushed_back_char = c;
  1621.   execute_command ("edit-cell");
  1622. }
  1623.  
  1624.  
  1625. /* File i/o */
  1626.  
  1627. int sneaky_linec = 0;    /* for error reporting for now (see io-term.c) */
  1628.  
  1629. #ifdef __STDC__
  1630. void 
  1631. read_cmds_cmd (FILE *fp)
  1632. #else
  1633. void 
  1634. read_cmds_cmd (fp)
  1635.      FILE *fp;
  1636. #endif
  1637. {
  1638.   struct line line;
  1639.   char *ptr;
  1640.   init_line (&line);
  1641.   sneaky_linec = 0;
  1642.   while (read_line (&line, fp, &sneaky_linec))
  1643.     {
  1644.       for (ptr = line.buf; isspace (*ptr); ptr++);
  1645.       if (!*ptr || (*ptr == '#'))
  1646.     continue;
  1647.       execute_command (ptr);
  1648.     }
  1649. }
  1650.  
  1651.  
  1652. static int run_load_hooks = 1;
  1653. static char load_hooks_string[] = "load_hooks";
  1654.  
  1655. #ifdef __STDC__
  1656. void
  1657. read_file_and_run_hooks (FILE * fp, int ismerge, char * name)
  1658. #else
  1659. void
  1660. read_file_and_run_hooks (fp, ismerge, name)
  1661.      FILE * fp;
  1662.      int ismerge;
  1663.      char * name;
  1664. #endif
  1665. {
  1666.   if (!ismerge)
  1667.     {
  1668.       if (current_filename)
  1669.     free (current_filename);
  1670.       current_filename = name ? ck_savestr (name) : 0;
  1671.     }
  1672.   (*read_file)(fp, ismerge);
  1673.   if (run_load_hooks)
  1674.     {
  1675.       struct var * v;
  1676.       v = find_var (load_hooks_string, sizeof (load_hooks_string) - 1);
  1677.       if (v && v->var_flags != VAR_UNDEF)
  1678.     execute_command (load_hooks_string);
  1679.     }
  1680. }
  1681.  
  1682. /* If TURN_ON is 0, this toggles whether load hooks are run.
  1683.  * Otherwise, it turns load hooks on.
  1684.  */
  1685.  
  1686. #ifdef __STDC__
  1687. void
  1688. toggle_load_hooks (int turn_on)
  1689. #else
  1690. void
  1691. toggle_load_hooks (turn_on)
  1692.      int turn_on;
  1693. #endif
  1694. {
  1695.   if (!turn_on && run_load_hooks)
  1696.     {
  1697.       run_load_hooks = 0;
  1698.       io_info_msg ("load hooks turned off");
  1699.     }
  1700.   else
  1701.     {
  1702.       run_load_hooks = 1;
  1703.       io_info_msg ("load hooks turned on");
  1704.     }
  1705. }
  1706.  
  1707. #ifdef __STDC__
  1708. void
  1709. write_cmd (FILE *fp, char * name)
  1710. #else
  1711. void
  1712. write_cmd (fp, name)
  1713.      FILE *fp;
  1714.      char * name;
  1715. #endif
  1716. {
  1717.   if (current_filename)
  1718.     free (current_filename);
  1719.   current_filename = name ? ck_savestr (name) : 0;
  1720.   (*write_file) (fp, 0);
  1721.   modified = 0;
  1722. }
  1723.  
  1724. #ifdef __STDC__
  1725. void
  1726. read_cmd (FILE *fp, char * name)
  1727. #else
  1728. void
  1729. read_cmd (fp, name)
  1730.      FILE *fp;
  1731.      char * name;
  1732. #endif
  1733. {
  1734.   read_file_and_run_hooks (fp, 0, name);
  1735. }
  1736.  
  1737. #ifdef __STDC__
  1738. void
  1739. read_merge_cmd (FILE *fp)
  1740. #else
  1741. void
  1742. read_merge_cmd (fp)
  1743.      FILE *fp;
  1744. #endif
  1745. {
  1746.   (*read_file) (fp, 1);
  1747. }
  1748.  
  1749. #ifdef __STDC__
  1750. void
  1751. write_reg_cmd (FILE *fp, struct rng *rng)
  1752. #else
  1753. void
  1754. write_reg_cmd (fp, rng)
  1755.      FILE *fp;
  1756.      struct rng *rng;
  1757. #endif
  1758. {
  1759.   (*write_file) (fp, rng);
  1760. }
  1761.  
  1762.  
  1763.  
  1764.  
  1765. /* Cell attributes. */
  1766. #ifdef __STDC__
  1767. void
  1768. set_region_height (struct rng * rng, char * height)
  1769. #else
  1770. void
  1771. set_region_height (rng, height)
  1772.      struct rng * rng;
  1773.      char * height;
  1774. #endif
  1775. {
  1776.   int hgt;
  1777.   char * saved_height = height;
  1778.  
  1779.   while (isspace (*height))
  1780.     ++height;
  1781.  
  1782.   if (   !*height
  1783.       || words_imatch (&height, "d")
  1784.       || words_imatch (&height, "def")
  1785.       || words_imatch (&height, "default"))
  1786.     hgt = 0;
  1787.   else
  1788.     {
  1789.       hgt = astol (&height) + 1;
  1790.       if (hgt < 0)
  1791.         /* noreturn */
  1792.     io_error_msg ("Height (%d) can't be less than 0.", hgt);
  1793.     }      
  1794.  
  1795.   if (*height)
  1796.     {
  1797.       io_error_msg ("Unknown height '%s'", saved_height);
  1798.       /* Doesn't return */
  1799.     }
  1800.   {
  1801.     CELLREF cc;
  1802.     for (cc = rng->lr; ;cc++)
  1803.       {
  1804.     set_height (cc, hgt);
  1805.     if (cc == rng->hr)    /* This test goes here to prevent overflow. */
  1806.       break;
  1807.       }
  1808.     io_recenter_all_win ();
  1809.   }
  1810. }
  1811.  
  1812. #ifdef __STDC__
  1813. void
  1814. set_region_width (struct rng * rng, char * width)
  1815. #else
  1816. void
  1817. set_region_width (rng, width)
  1818.      struct rng * rng;
  1819.      char * width;
  1820. #endif
  1821. {
  1822.   char * saved_width = width;
  1823.   int wid;
  1824.  
  1825.   while (isspace (*width))
  1826.     ++width;
  1827.  
  1828.   if (   !*width
  1829.       || words_imatch (&width, "d")
  1830.       || words_imatch (&width, "def")
  1831.       || words_imatch (&width, "default"))
  1832.     wid = 0;
  1833.   else
  1834.     {
  1835.       wid = astol (&width) + 1;
  1836.       if (wid < 0)
  1837.         /* noreturn */
  1838.     io_error_msg ("Width (%d) can't be less than 0.", wid);
  1839.     }      
  1840.  
  1841.   if (*width)
  1842.     {
  1843.       io_error_msg ("Unknown width '%s'", saved_width);
  1844.       /* No return. */
  1845.     }
  1846.   {
  1847.     CELLREF cc;
  1848.     for (cc = rng->lc; ;cc++)
  1849.       {
  1850.     set_width (cc, wid);
  1851.     if (cc == rng->hc)    /* This test goes here to prevent overflow. */
  1852.       break;
  1853.       }
  1854.     io_recenter_all_win ();
  1855.   }
  1856. }
  1857.  
  1858.  
  1859. /* PROT may be `d', `p', or `u'. */
  1860.  
  1861. #ifdef __STDC__
  1862. void
  1863. set_region_protection (struct rng * rng, int prot)
  1864. #else
  1865. void
  1866. set_region_protection (rng, prot)
  1867.      struct rng * rng;
  1868.      int prot;
  1869. #endif
  1870. {
  1871.   if (isupper (prot))
  1872.     prot = tolower (prot);
  1873.   switch (prot)
  1874.     {
  1875.     case 'd':
  1876.       lock_region (rng, LCK_DEF);
  1877.       break;
  1878.     case 'p':
  1879.       lock_region (rng, LCK_LCK);
  1880.       break;
  1881.     case 'u':
  1882.       lock_region (rng, LCK_UNL);
  1883.       break;
  1884.     default:
  1885.       io_error_msg ("Bad argument to protect-region %c.", prot);
  1886.       break;
  1887.     }
  1888. }
  1889.  
  1890. #ifdef __STDC__
  1891. void
  1892. set_region_alignment (struct rng * rng, int align)
  1893. #else
  1894. void
  1895. set_region_alignment (rng, align)
  1896.      struct rng * rng;
  1897.      int align;
  1898. #endif
  1899. {
  1900.   int fun = chr_to_jst (align);
  1901.   if (fun != -1)
  1902.     format_region (rng, -1, fun);
  1903.   else            /* if (main_map[align]!=BREAK_CMD) */
  1904.     io_error_msg ("Unknown Justify '%s'", char_to_string (align));
  1905. }
  1906.  
  1907. #ifdef __STDC__
  1908. void
  1909. set_region_format (struct rng * rng, int fmt)
  1910. #else
  1911. void
  1912. set_region_format (rng, fmt)
  1913.      struct rng * rng;
  1914.      int fmt;
  1915. #endif
  1916. {
  1917.   format_region (rng, fmt, -1); 
  1918. }
  1919.  
  1920.  
  1921.  
  1922.  
  1923. #ifdef __STDC__
  1924. void
  1925. set_def_height (char * height)
  1926. #else
  1927. void
  1928. set_def_height (height)
  1929.      char * height;
  1930. #endif
  1931. {
  1932.   char * saved_height = height;
  1933.   int hgt;
  1934.  
  1935.   while (isspace (*height))
  1936.     ++height;
  1937.  
  1938.   if (   !*height
  1939.       || words_imatch (&height, "d")
  1940.       || words_imatch (&height, "def")
  1941.       || words_imatch (&height, "default"))
  1942.     hgt = 1;
  1943.   else
  1944.     {
  1945.       hgt = astol (&height);
  1946.       if (hgt < 0)
  1947.         /* noreturn */
  1948.     io_error_msg ("Height (%d) can't be less than 0.", hgt);
  1949.     }      
  1950.  
  1951.   if (*height)
  1952.     {
  1953.       io_error_msg ("Unknown height '%s'", saved_height);
  1954.       /* No return. */
  1955.     }
  1956.   default_height = hgt;
  1957.   io_recenter_all_win ();
  1958. }
  1959.  
  1960. #ifdef __STDC__
  1961. void
  1962. set_def_width (char * width)
  1963. #else
  1964. void
  1965. set_def_width (width)
  1966.      char * width;
  1967. #endif
  1968. {
  1969.   char * saved_width = width;
  1970.   int wid;
  1971.  
  1972.   while (isspace (*width))
  1973.     ++width;
  1974.  
  1975.   if (   !*width
  1976.       || words_imatch (&width, "d")
  1977.       || words_imatch (&width, "def")
  1978.       || words_imatch (&width, "default"))
  1979.     wid = 8;
  1980.   else
  1981.     {
  1982.       wid = astol (&width);
  1983.       if (wid < 0)
  1984.         /* noreturn */
  1985.     io_error_msg ("Width (%d) can't be less than 0.", wid);
  1986.     }      
  1987.  
  1988.   if (*width)
  1989.     {
  1990.       io_error_msg ("Unknown width '%s'", saved_width);
  1991.       /* No return. */
  1992.     }
  1993.   default_width = wid;
  1994.   io_recenter_all_win ();
  1995. }
  1996.  
  1997. /* PROT may be `d', `p', or `u'. */
  1998.  
  1999. #ifdef __STDC__
  2000. void
  2001. set_def_protection (int prot)
  2002. #else
  2003. void
  2004. set_def_protection (prot)
  2005.      int prot;
  2006. #endif
  2007. {
  2008.   if (isupper (prot))
  2009.     prot = tolower (prot);
  2010.   switch (prot)
  2011.     {
  2012.     case 'p':
  2013.       default_lock = LCK_LCK;
  2014.       break;
  2015.     case 'u':
  2016.       default_lock = LCK_UNL;
  2017.       break;
  2018.     default:
  2019.       io_error_msg ("Bad argument to set-default-protection %c.", prot);
  2020.       break;
  2021.     }
  2022. }
  2023.  
  2024. #ifdef __STDC__
  2025. void
  2026. set_def_alignment (int align)
  2027. #else
  2028. void
  2029. set_def_alignment (align)
  2030.      int align;
  2031. #endif
  2032. {
  2033.   int fun = chr_to_jst (align);
  2034.   if (fun == -1)
  2035.     io_error_msg ("Unknown justification.");
  2036.  
  2037.   default_jst = fun;
  2038.   io_repaint ();
  2039. }
  2040.  
  2041. #ifdef __STDC__
  2042. void
  2043. set_def_format (int fmt)
  2044. #else
  2045. void
  2046. set_def_format (fmt)
  2047.      int fmt;
  2048. #endif
  2049. {
  2050.   default_fmt = fmt;
  2051.   io_repaint ();
  2052. }
  2053.  
  2054.  
  2055.  
  2056. #ifdef __STDC__
  2057. void
  2058. define_usr_fmt (int fmt, char * pos_h, char * neg_h, char * pos_t,
  2059.         char * neg_t, char * zero, char * comma, char * decimal,
  2060.         char * precision, char * scale)
  2061. #else
  2062. void
  2063. define_usr_fmt (fmt, pos_h, neg_h, pos_t, neg_t, zero,
  2064.         comma, decimal, precision, scale)
  2065.      int fmt;
  2066.      char * pos_h;
  2067.      char * neg_h;
  2068.      char * pos_t;
  2069.      char * neg_t;
  2070.      char * zero;
  2071.      char * comma;
  2072.      char * decimal;
  2073.      char * precision;
  2074.      char * scale;
  2075. #endif
  2076. {
  2077.   char * usr_buf[9];
  2078.   if (fmt < 1 || fmt > 16)
  2079.     {
  2080.       io_error_msg ("Format number out of range %d (should be in [1..16].",
  2081.             fmt);
  2082.       /* no return */
  2083.     }
  2084.   /* Vector to an older interface... */
  2085.   --fmt;
  2086.   usr_buf[0] = pos_h;
  2087.   usr_buf[1] = neg_h;
  2088.   usr_buf[2] = pos_t;
  2089.   usr_buf[3] = neg_t;
  2090.   usr_buf[4] = zero;
  2091.   usr_buf[5] = comma;
  2092.   usr_buf[6] = decimal;
  2093.   usr_buf[7] = precision;
  2094.   usr_buf[8] = scale;
  2095.   set_usr_stats (fmt, usr_buf);
  2096. }
  2097.  
  2098.  
  2099.  
  2100. /* Automatic motion while editting cell's: */
  2101.  
  2102. /* Hmm... where should this variable *really* go? */
  2103.  
  2104. static int auto_motion_direction = magic_down;
  2105.  
  2106. #ifdef __STDC__
  2107. void
  2108. set_auto_direction (enum motion_magic magic)
  2109. #else
  2110. void
  2111. set_auto_direction (magic)
  2112.      enum motion_magic magic;
  2113. #endif
  2114. {
  2115.   auto_motion_direction = magic;
  2116.   io_info_msg ("Auto-motion direction = %s.", motion_name[magic]);
  2117. }
  2118.  
  2119. #ifdef __STDC__
  2120. void
  2121. auto_move (void)
  2122. #else
  2123. void
  2124. auto_move ()
  2125. #endif
  2126. {
  2127.   shift_cell_cursor (auto_motion_direction, 1);
  2128. }
  2129.  
  2130. #ifdef __STDC__
  2131. void
  2132. auto_next_set (void)
  2133. #else
  2134. void
  2135. auto_next_set ()
  2136. #endif
  2137. {
  2138.   scan_cell_cursor (opposite_motion[auto_motion_direction], 1);
  2139.   {
  2140.     CELL * cp = find_cell (curow, cucol);
  2141.     if (!cp || !GET_TYP(cp))
  2142.       shift_cell_cursor (auto_motion_direction, 1);
  2143.   }
  2144.   shift_cell_cursor (complementary_motion[auto_motion_direction], 1);
  2145. }
  2146.  
  2147.  
  2148. /* This decompiles and then recompiles all of the formulas of cells.
  2149.  * This is never normally necessary unless you happen to have some
  2150.  * spreadsheets written when the byte-code compiler had bugs that
  2151.  * made your formulas produce parse errors.
  2152.  */
  2153.  
  2154. #ifdef __STDC__
  2155. void
  2156. recompile_spreadsheet (void)
  2157. #else
  2158. void
  2159. recompile_spreadsheet ()
  2160. #endif
  2161. {
  2162.   struct rng rng;
  2163.   CELL * cp;
  2164.   CELLREF r;
  2165.   CELLREF c;
  2166.   rng.lr = MIN_ROW;
  2167.   rng.lc = MIN_COL;
  2168.   rng.hr = MAX_ROW;
  2169.   rng.hc = MAX_COL;
  2170.   find_cells_in_range (&rng);
  2171.   for (cp = next_row_col_in_range (&r, &c);
  2172.        cp;
  2173.        cp = next_row_col_in_range(&r, &c))
  2174.     {
  2175.       char * form = decomp (r, c, cp);
  2176.       set_cell (r, c, form);
  2177.       if (my_cell)
  2178.     {
  2179.       update_cell (my_cell);
  2180.       if (is_constant (my_cell->cell_formula))
  2181.         {
  2182.           byte_free (my_cell->cell_formula);
  2183.           my_cell->cell_formula = 0;
  2184.         }
  2185.       io_pr_cell (r, c, my_cell);
  2186.       my_cell = 0;
  2187.     }
  2188.       decomp_free ();
  2189.     }
  2190. }
  2191.  
  2192.